﻿#pragma once

#include <coroutine>
#include <iostream>
#include <thread>
#define LOG_THREAD(str) std::cout << "[" << std::this_thread::get_id() << "][" << __FUNCTION__ << "]" << str << "\n";

//
//template<typename T, typename Awaitable>
//std::future<T> as_promise(Awaitable&& awaiter)
//	requires(!std::is_void_v<T>)
//{
//	std::promise<T> promise;
//	auto res = promise.get_future();
//	[](std::decay_t<Awaitable> awaiter, std::promise<T> promise) -> eager_fire_and_forget_task<> {
//		try {
//			promise.set_value(co_await std::move(awaiter));
//		}
//		catch (...) { promise.set_exception(std::current_exception()); }
//		}(std::forward<decltype(awaiter)>(awaiter), std::move(promise));
//	return res;
//}
//
///**
// * \brief Execute the given awaitable and return a std::promise representing the call.
// * \note The returned promise will block until the async function finishes or throws.
// *
// * This can be used to synchronously wait for the result of a coroutine.
// */
//template<typename T, typename Awaitable>
//std::future<void> as_promise(Awaitable&& awaiter)
//	requires(std::is_void_v<T>)
//{
//	std::promise<void> promise;
//	auto res = promise.get_future();
//	[](std::decay_t<Awaitable> awaiter, std::promise<void> promise) -> eager_fire_and_forget_task<> {
//		try {
//			co_await std::move(awaiter);
//			promise.set_value();
//		}
//		catch (...) { promise.set_exception(std::current_exception()); }
//		}(std::forward<decltype(awaiter)>(awaiter), std::move(promise));
//	return res;
//}

//struct promise_base
//{
//	std::suspend_never initial_suspend() { return {}; }
//	std::suspend_never final_suspend() noexcept { return {}; }
//	void unhandled_exception()
//	{
//		std::exit(1);
//	}
//};
//
//template <typename T>
//struct task
//{
//	struct promise_type;
//	using handle_type = std::coroutine_handle<promise_type>;
//	struct promise_type : public promise_base
//	{
//		task get_return_object()
//		{
//			return { .handle = handle_type::from_promise(*this) };
//		}
//		void return_value(T _value)
//		{
//			value = _value;
//		} // 調用co_return
//		T value{};
//	};
//	T get()
//	{
//		return handle.promise().value;
//	}
//	handle_type handle;
//};
//
//template <>
//struct task<void>
//{
//	struct promise_type;
//	using handle_type = std::coroutine_handle<promise_type>;
//	struct promise_type : public promise_base
//	{
//		task get_return_object()
//		{
//			return { handle_type::from_promise(*this) };
//		}
//		void return_void() {}
//	};
//	handle_type handle;
//};
//
//template <typename P, typename F>
//	requires std::invocable<F, std::coroutine_handle<P>&>
//struct awaiter
//{
//	using handle_type = std::coroutine_handle<P>;
//	explicit awaiter(F _f) : f(_f) {}
//	bool await_ready() { return false; }
//	void await_suspend(handle_type _handle) // _handle為傳入的task::handle
//	{
//		f(_handle); // 暫停時調用
//	}
//	void await_resume() {}
//	F f;
//};
//
///// @brief 在協程中處理回調
///// @param _handle 協程柄
///// @param _f 回調
///// @return 可供co_await的協程
//template <typename P, std::invocable F>
//inline auto async_resume(std::coroutine_handle<P>& _handle, F _f)
//{
//	using handle_type = std::coroutine_handle<P>;
//	auto fn = [&_handle, _f](const handle_type& _hdl)
//		{
//			_handle = _hdl; // 把協程句柄傳出去
//			_f();           // 業務回調
//		};
//	return awaiter<P, decltype(fn)>{fn};
//}
//
//template <typename P, typename T, typename F>
//	requires std::invocable<F, std::coroutine_handle<P>&, T&>
//struct awaiter_value
//{
//	using handle_type = std::coroutine_handle<P>;
//	explicit awaiter_value(F _f) : f(_f) {}
//	bool await_ready() { return false; }
//	void await_suspend(handle_type _handle)
//	{
//		f(_handle, value);
//	}
//	T await_resume() { return value; } // 這裡就是co_await的返回值
//	F f;
//	T value{}; // 用於保存co_await的返回值
//};
//
///// @brief 在協程中處理回調並返回值
///// @param _handle 協程柄
///// @param _f 回調
///// @return 可供co_await的協程
//template <typename T, typename P, typename F>
//	requires std::invocable<F, T&>
//inline auto async_resume_value(std::coroutine_handle<P>& _handle, F _f)
//{
//	using handle_type = std::coroutine_handle<P>;
//	auto fn = [&_handle, _f](const handle_type& _hdl, T& _value)
//		{
//			_handle = _hdl;
//			_f(_value);
//		};
//	return awaiter_value<P, T, decltype(fn)>{fn};
//}
//
//#include <tuple>
//#include <system_error>
//using result_type = std::tuple<std::error_code, std::size_t>;
//
//template <typename P>
//struct asio_callback
//{
//	using handle_type = std::coroutine_handle<P>;
//	asio_callback(handle_type& _handle, result_type& _result)
//		: handle(_handle), result(_result) {}
//	~asio_callback() {}
//	/// @brief 獲取回調的兩個值
//	void operator()(std::error_code _error, std::size_t _bytes)
//	{
//		result = std::make_tuple(_error, _bytes); // 打包返回值
//		handle.resume();                          // 恢復協程
//	}
//
//private:
//	result_type& result;
//	handle_type& handle;
//};
//
//namespace as
//{
//	template<typename T>
//	struct TaskPromise {
//		struct promise_type {
//			TaskPromise get_return_object() {
//				std::cout << "get_return_object(), thread_id: " << std::this_thread::get_id() << std::endl;
//				return TaskPromise{ std::coroutine_handle<promise_type>::from_promise(*this) };
//			}
//			std::suspend_always initial_suspend() noexcept { return {}; }
//			std::suspend_always final_suspend() noexcept { return {}; }
//			void unhandled_exception() {}
//			void return_value(T& t) noexcept {
//				data = std::addressof(t);
//			}
//			T* data = nullptr;
//		};
//		std::coroutine_handle<promise_type> handle;
//	};
//
//	template<typename T>
//	struct Awaiter {
//		using AwaiterPromiseType = TaskPromise<T>::promise_type;
//		bool await_ready() noexcept {
//			std::cout << "await_ready(), thread_id: " << std::this_thread::get_id() << std::endl;
//			return false;
//		}
//		void await_suspend(std::coroutine_handle<AwaiterPromiseType> handle) noexcept {
//			std::cout << "await_suspend(), thread_id: " << std::this_thread::get_id() << std::endl;
//			auto thread = std::thread([=]() {
//				std::this_thread::sleep_for(std::chrono::seconds(1));
//				int* i = new int();
//				*i = 10;
//				handle.promise().data = i;
//				std::cout << "await_resume() jthread done:" << std::this_thread::get_id() << std::endl;
//				handle.resume();
//				});
//			thread.join();
//		}
//		void await_resume() noexcept {
//			std::cout << "await_resume(), thread_id: " << std::this_thread::get_id() << std::endl;
//		}
//	};
//}
//

